perm filename UPDATE.FAI[HST,NET]14 blob sn#826027 filedate 1986-10-12 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00015 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00004 00002	TITLE UPDATE  History FTPUP A B C D E H X P DIN DOUT DVER ERR PUPVER PUPEFT SRINIC SRINIC HNSPRT PDLEN BUFLEN NICVER DSKVER ENDMK ENDEND FTPCOM PTYJOB DIRHLN DIRHDR VERPTR VERLSN VERSTS VERTRM VERCON VCNSTS VERHST EFTGEN EFTGSK EFTLSN EFTSTS EFTLSK EFTHST PUPMAX PKTBUF PKTLEN PKTTYP PKTDST PKTSRC PKTBFD PUPOVH OURHST PUPDSV PUPMSV PUPMHS PDL DIBUF DOBUF DVIBUF DVOBUF PUPIBF ERBUF ERRORS CHANGE CRLF MAIHD1 MAIHD2 MAIHD3 MAIBLK NIORTS ERRTNS PUPDIR PUPHSP NUMNAM NAMLKP NUMADR ADRLKP NUMENT FSTENT PUPVRS HDRSIZ ENTPTR NAMPTR ADRPTR CPUPTR OPSPTR NETPTR PRTPTR SHOWIP DOMSTR DOMHST DOMNAM DOMNUM
C00020 00003	LOOKUP/ENTER blocks for files  VERFIL HSTFIL ERRFIL DIRFIL PHSFIL
C00021 00004	Output subroutines  NETSTR NETST1 DECOUT OCTOUT OCTOU1 CPOPJ2 CPOPJ1 CPOPJ
C00023 00005	Error handling  MESTYP MESTY1 MAILMS ERRERR
C00026 00006	Get and compare NIC version strings  VERNIC VERNI1 VERNI2 VERIN VERIN1 VERIN2 VEROUT VEROU1 VEROU2 VERCOM VERCO1
C00032 00007	Get new NIC table from Host Name Server  NEWNIC NEWNI1 NEWNI2 NEWNI3
C00036 00008	FTP new HOSTS3.BIN from NIC  NEWNIC NEWNI1 NEWNI2 NEWNI3
C00040 00009	Read PUP directory version number  RDPVER RDPDIR
C00043 00010	Get PUP version from Ethernet  GETVER GETVE1
C00047 00011	Get new PUP directory  GNPDIR GNPDI1 GNPDI2 GNPDI3 GNPDI4 GETCOR GETCO1
C00053 00012	File output routines  PUTCH PUTCH1 PUTSTR PUTST1 PUTDEC PUTOCT PUTOC1 PUTSIX PUTDAT MONTH
C00056 00013	More subroutines  IPTEST IPTES1 IPTES2 IPTES3 OUTADR OUTAD1 OUTNAM OUTNLP COMPAR COMPLP COMPL1 COMPL2 CMPLUZ PUTATR PUTALP PUTAT1
C00065 00014	Create PUPHST.TXT file  PUPHST HDRLP MAINLP ALLDUN REDENT ATTLP ATTLP1 SHORT PRCENT
C00072 00015	Top level  NICUPD NICERR PUPUPD PUPERR PUPHAK UPDATE PPNOK NOERRS
C00078 ENDMK
C⊗;
TITLE UPDATE ;⊗ History FTPUP A B C D E H X P DIN DOUT DVER ERR PUPVER PUPEFT SRINIC SRINIC HNSPRT PDLEN BUFLEN NICVER DSKVER ENDMK ENDEND FTPCOM PTYJOB DIRHLN DIRHDR VERPTR VERLSN VERSTS VERTRM VERCON VCNSTS VERHST EFTGEN EFTGSK EFTLSN EFTSTS EFTLSK EFTHST PUPMAX PKTBUF PKTLEN PKTTYP PKTDST PKTSRC PKTBFD PUPOVH OURHST PUPDSV PUPMSV PUPMHS PDL DIBUF DOBUF DVIBUF DVOBUF PUPIBF ERBUF ERRORS CHANGE CRLF MAIHD1 MAIHD2 MAIHD3 MAIBLK NIORTS ERRTNS PUPDIR PUPHSP NUMNAM NAMLKP NUMADR ADRLKP NUMENT FSTENT PUPVRS HDRSIZ ENTPTR NAMPTR ADRPTR CPUPTR OPSPTR NETPTR PRTPTR SHOWIP DOMSTR DOMHST DOMNAM DOMNUM

COMMENT ⊗

This is a WAITS program to automatically update NIC and PUP host tables.
It runs at SAIL and S1-A (LLL), with different code chosen by assembly switches.

Written by Joe Weening, SU-AI, July 1983.

Currently, this program does the following:
1. Gets the version number of the current host table from the host name server
   at SRI-NIC, and compares it with the version number of our file.  The version
   number is stored as a character string in the file HOSTS.VER[HST,NET].  If
   needed, a new host table is retrieved.  For S1-A, the binary HOSTS3 table is
   retrieved using FTP on a PTY subjob into HOSTS3.BIN[HST,NET].  For SAIL, the
   text table is retrieved from the host name server into HOSTS.TXT[HST,NET].
2. For SAIL, sends out the version number of our PUP network directory, and
   collects replies indicating higher version numbers at other Ethernet sites.
   Updates the directory, kept as the binary file PUPNET.DIR[HST,NET], if a
   newer version is present, and converts this to a text version in RFC810
   format, stored as PUPHST.TXT[HST,NET].

Future plans include the following:
3. Merge the text form of the NIC and PUP tables into a binary HOSTS3-format
   table, and store it as HOSTS3.BIN[HST,NET].  This can now be done with the
   HOSTS3 program.  (Perhaps should load "do merge" into TTY input buffer.)


   Jul 83 JJW	Initial implementation (get HOSTS.TXT from NIC Hostname server).
   Sep 83 JJW	Get binary PUP network directory using PUP network directory
		update protocol.  Conversion to text form done by separate program.
18-Dec-83 JJW	Merged in PUPHST code from separate program.
27-Jan-84 JJW	FTLLL etc. defined from WATSIT[S,SYS].  FTPUP switch introduced.
11-Feb-84 JJW	FTLLL code to get HOSTS3.BIN from NIC, running FTP on a PTY.
02-Mar-84 JJW	PUPHST includes domain-style names for known hosts in NIC table.
14-Mar-84 JJW	PUPHST shows IP addresses based on "Networks" attribute.
14-Apr-84 JJW	Domain-style names no longer produced; HOSTS3 now merges based
		on host address.
18-May-84 JJW	PUP version number shown in decimal, not octal.
07-Mar-85 JJW	Increase FTP timeout to 120 seconds.  Table is getting big!
23-Apr-86 JJW	Construct domain name, and allow lowercase in output.
31-May-86 JJW	Get combined NIC/Stanford table from Argus.
12-Oct-86 JJW	Took out one kludge in GERVER, added one in GNPDIR to deal
		with multi-homed Vaxen using a different address for EFTP
		than for Pup version reply.  Allow Argus host table to be
		received without endmark, since it happens so often.

History: end of comment ⊗
PRINTS /Have you listed your changes at History: on page 2?
/

;Switch definitions
.INSERT WATSIT[S,SYS]		;Define FTSUAI, FTLLL, etc.
FTPUP←←IFN FTLLL,<0;>-1		;Everyone except LLL is a Stanford PUP site

A←1				;AC definitions
B←2
C←3
D←4
E←5
H←10
X←11
P←17

;I/O channels.  0, 1, and 2 are reserved for NETWRK, used for IMP I/O.
;NETWRK is not used for PUP I/O, since it doesn't handle packet and EFTP modes.

DIN←←3				;Disk input channel
DOUT←←4				;Disk output channel
DVER←←5				;Disk channel for HOSTS.VER file
ERR←←6				;Disk channel for error message file
IFN FTPUP,<
PUPVER←←7			;PUP channel for version request
PUPEFT←←10			;PUP channel for EFTP directory update
>;IFN FTPUP

;Host number for SRI-NIC.  We could use HSTNAM in NETWRK, but then we'd lose if
;there was something wrong with the host table.
IFN FTSUAI,<
repeat 0,<
SRINIC←←<BYTE (4)0(8)=10,0,0,=51> ;ARPAnet address
>;repeat 0
;JJW 5/31/86 use table from Argus with Stanford entries added to NIC table.
SRINIC←←<BYTE (4)0(8)=36,=53,0,=10>	;Argus.Stanford.EDU
>;IFN FTSUAI
IFN FTLLL,<
SRINIC←←<BYTE (4)0(8)=26,0,0,=73> ;MILnet address
>;IFN FTLLL
HNSPRT←←=101			;Host Name Server port number

IFN FTPUP,<MSCSKT←←4>		;Misc. server socket number

;Other definitions
PDLEN←←20			;Stack
BUFLEN←←40			;Length of various blocks

;Data for NIC table update

NICVER:	BLOCK BUFLEN		;Version string from NIC
DSKVER:	BLOCK BUFLEN		;Version string on disk

IFE FTLLL,<
ENDMK:	12			;Chars that mark end of NIC host table
	"E"
	"N"
	"D"
ENDEND←←.
>;IFE FTLLL

IFN FTLLL,<
				;Command line typed on PTY to run FTP.
FTPCOM:	ASCIZ*FTP/Q HOSTS3.BIN←{26.0.0.73}<NETINFO>HOSTS3.BIN
*
PTYJOB:	BLOCK 1			;Job number of job created on PTY for FTP
>;IFN FTLLL

IFN FTPUP,<
;Definitions for reading header of PUP network directory from file

DIRHLN←←4			;Number of header words to read
DIRHDR:	BLOCK DIRHLN
VERPTR:	POINT 16,DIRHDR+3,15	;Byte ptr for version number

;MTAPE blocks for PUP operations

VERLSN:	1			;Listen block for PUP version request
VERSTS:	0			;Status bits returned
	-1			;Local socket
	0			;Don't wait
	=8			;Byte size
	MSCSKT			;Foreign socket
	-1			;Foreign host (broadcast)

VERTRM:	3			;Terminate block for PUPVER
	0			;Status
	0			;Local socket
	0			;Don't wait

VERCON:	0			;Connect block for PUPVER
VCNSTS:	0			;Status
	-1			;Local socket
	-1			;Do wait (though in packet mode we won't)
	=8			;Byte size
	MSCSKT			;Foreign socket
VERHST:	0			;Foreign host

EFTGEN:	21			;Gensym block for EFTP socket
EFTGSK:	0

EFTLSN:	1			;Listen block for EFTP
EFTSTS:	0			;Status bits returned
EFTLSK:	0			;Local socket
	0			;Don't wait
	=8			;Byte size
	-1			;Foreign socket (whatever they choose)
EFTHST:	0			;Foreign host

;Definitions for sending packet-mode PUPs

PUPMAX←←=140			;Maximum PUP packet length
PKTBUF:	BLOCK PUPMAX		;PUP packet buffer

;Pointers into PKTBUF

PKTLEN:	POINT 16,PKTBUF,15	;PUP length (in bytes)
PKTTYP:	POINT 16,PKTBUF,31	;PUP Type
PKTDST:	POINT 16,PKTBUF+2,15	;PUP Destination host
PKTSRC:	POINT 16,PKTBUF+3,31	;PUP Source host
PKTBFD←←PKTBUF+5		;Location of data within PUP
PUPOVH←←=22			;Number of overhead bytes in a PUP

;Data for PUP network directory update

OURHST:	BLOCK 1			;Our PUP address (from an incoming packet)
PUPDSV:	BLOCK 1			;PUP directory on disk's version number
PUPMSV:	BLOCK 1			;Highest version number from misc. servers
PUPMHS:	BLOCK 1			;Host number that has highest version

>;IFN FTPUP

;Other things

PDL:	BLOCK PDLEN
DIBUF:	BLOCK 3			;Buffer headers
DOBUF:	BLOCK 3
DVIBUF:	BLOCK 3
DVOBUF:	BLOCK 3
IFN FTPUP,<
PUPIBF:	BLOCK 3
>;IFN FTPUP
ERBUF:	BLOCK 3
ERRORS:	0			;-1 if we have errors
CHANGE:	0			;-1 if anything changed
CRLF:	BYTE (7)15,12

;Definitions for error messages

DEFINE MESSAG(MESS) <
	JRST [  MOVEI A,[ASCIZ\MESS
\]
		JRST MESTYP]
>

;Header lines for error message file
MAIHD1:	ASCIZ\MAIL/SUBJECT BUG-HOST\
MAIHD2:	BYTE (7)15,12,14	;CRLF,FF
MAIHD3:	ASCIZ/Report from UPDATE of host tables

/

;Data block for SWAP UUO
MAIBLK:	SIXBIT/SYS/
	SIXBIT/MAIL/
	SIXBIT/DMP/
	0,,1			;RPG startup
	0
	0

NIORTS←←-1			;Use network I/O routines for IMP
ERRTNS←←-1			;Error routines
.INSERT NETWRK.FAI[S,NET]	;Wonderful network I/O package

IFN FTPUP,<
PUPDIR:	BLOCK 1			;Address of PUP directory read in
PUPHSP:	BLOCK 1			;Saved PDL ptr

;Data from header block in PUP directory.  All blocks and tables are guaranteed
;to be on an even 16-bit byte boundary, i.e., at the start of a PDP-10 word.
NUMNAM:	BLOCK 1			;Number of name blocks
NAMLKP:	BLOCK 1			;Pointer to name lookup table
NUMADR:	BLOCK 1			;Number of address blocks
ADRLKP:	BLOCK 1			;Pointer to address lookup table
NUMENT:	BLOCK 1			;Number of 16-bit words occupied by entry blocks
FSTENT:	BLOCK 1			;Pointer to first entry block
PUPVRS:	BLOCK 1			;Version of PUP directory
HDRSIZ←←.-NUMNAM		;Size of header block

ENTPTR:	BLOCK 1			;Byte pointer to step through entry blocks
;Following words are all host addresses in network directory for current entry
NAMPTR:	BLOCK 1			;Ptr to 1st name block
ADRPTR:	BLOCK 1			;Ptr to 1st address block
CPUPTR:	BLOCK 1			;CPU attribute string
OPSPTR:	BLOCK 1			;Op-System
NETPTR:	BLOCK 1			;Networks
PRTPTR:	BLOCK 1			;Protocols

SHOWIP:	BLOCK 1			;Non-zero to show IP addresses for current entry

repeat 0,<		;no longer needed
;For the HOSTS3 program to match entries of Stanford hosts, we make PUPHST.TXT
;contain domain-style names in addition to the names in the PUP network
;directory.  This is done in a rather ad-hoc fashion.

DEFINE SHOSTS<
SHOST(50,135,SU-CSLI.ARPA)
SHOST(50,300,SU-SHASTA.ARPA)
SHOST(50,301,SU-HNV.ARPA)
SHOST(50,302,SU-AI.ARPA)
SHOST(50,303,SU-SCORE.ARPA)
SHOST(50,310,SU-DSN.ARPA)
SHOST(50,313,SU-NAVAJO.ARPA)
SHOST(50,314,SU-WHITNEY.ARPA)
SHOST(50,315,SU-GLACIER.ARPA)
SHOST(50,324,SU-CARMEL.ARPA)
SHOST(50,325,SU-SIERRA.ARPA)
SHOST(50,327,SU-COYOTE.ARPA)
SHOST(50,330,SU-CASCADE.ARPA)
SHOST(55,125,SU-ARDVAX.ARPA)
SHOST(55,126,SU-SAFE.ARPA)
SHOST(55,127,SUMEX-AIM.ARPA)
>;DEFINE SHOSTS

DOMSTR:	BLOCK 1			;Addr of domain name to use, if non-zero
DEFINE SHOST(A,B,NAME)<
	A⊗10+B
>
DOMHST:	SHOSTS

DEFINE SHOST(A,B,NAME)<
	[ASCIZ/NAME, /]
>
DOMNAM:	SHOSTS
DOMNUM←←.-DOMNAM
>;repeat 0

>;IFN FTPUP
;LOOKUP/ENTER blocks for files ;⊗ VERFIL HSTFIL ERRFIL DIRFIL PHSFIL

VERFIL:	SIXBIT/HOSTS/		;File with NIC version string
	SIXBIT/VER/
	0
	0

IFE FTLLL,<
HSTFIL:	SIXBIT/HOSTS/		;NIC host table
	SIXBIT/TXT/
	0
	0
>;IFE FTLLL

ERRFIL:	SIXBIT/$MAIL/		;Error message mail file
	SIXBIT/TMP/
	0
	0

IFN FTPUP,<
DIRFIL:	SIXBIT/PUPNET/		;PUP network directory
	SIXBIT/DIR/
	0
	0

PHSFIL:	SIXBIT/PUPHST/		;PUP text file
	SIXBIT/TXT/
	0
	0
>;IFN FTPUP
;Output subroutines ;⊗ NETSTR NETST1 DECOUT OCTOUT OCTOU1 CPOPJ2 CPOPJ1 CPOPJ

;Output a string to current network connection.  Call:
;	MOVEI A,[ASCIZ/string/]
;	PUSHJ P,NETSTR
;	<error return>
;	<normal return>
;Clobbers 0 and A.
NETSTR:	HRLI A,440700		;Make byte ptr
NETST1:	ILDB 0,A		;Get char
	JUMPE 0,CPOPJ1		;All done
	PUSHJ P,NETOCH		;Send char
	 POPJ P,		;Error return
	JRST NETST1

;Numeric output routines.  Call with number in A, clobbers B and C.

DECOUT:	SKIPA C,[=10]		;Decimal
OCTOUT:	MOVEI C,=8		;Octal
OCTOU1:	IDIVI A,(C)
	HRLM B,(P)
	JUMPE A,.+2
	PUSHJ P,OCTOU1
	HLRZ B,(P)
	ADDI B,"0"
	OUTCHR B
	POPJ P,

CPOPJ2:	AOS (P)
CPOPJ1:	AOS (P)
CPOPJ:	POPJ P,
;Error handling ;⊗ MESTYP MESTY1 MAILMS ERRERR

;Error message handler.  Generally the MESSAG macro is used on errors, which
;causes a jump to here.  This then does a POPJ P, which indicates to the next
;level up that there was an error.

MESTYP:	OUTSTR (A)		;Type error message on terminal
	HRLI A,440700		;Make byte ptr
	SKIPGE ERRORS		;Have there been previous errors?
	JRST MESTY1		;Yes, add current text to output
	SETOM ERRORS		;No, this is the first time we're here
	PUSH P,A		;Save ptr while we output header
	INIT ERR,0		;Open error file
	 SIXBIT/DSK/
	 ERBUF,,0
	 JRST ERRERR
	SETZM ERRFIL+3		;Create error file on our area
	ENTER ERR,ERRFIL
	 JRST ERRERR
	MOVE A,[POINT 7,MAIHD1]
	PUSHJ P,MESTY1		;Output first part of header
	MOVE A,[POINT 7,MAIHD2]
	PUSHJ P,MESTY1		;Second part
	MOVE A,[POINT 7,MAIHD3]
	PUSHJ P,MESTY1		;Third part
	POP P,A			;Now output message
MESTY1:	ILDB 0,A
	JUMPE 0,CPOPJ
	SOSG ERBUF+2
	OUT ERR,
	 CAIA
	JRST ERRERR
	IDPB 0,ERBUF+1
	JRST MESTY1

;Here to mail accumulated error text.
MAILMS:	RELEAS ERR,		;Write out error file
	MOVE 14,ERRFIL		;Set input filename for MAIL
	MOVE 13,ERRFIL+1
	MOVEI 11,0		;File is on alias area
	MOVEI 12,0		;No returned message
	MOVEI 0,MAIBLK
	SWAP 0,			;Swap to mail
	POPJ P,			;Return if we get back somehow

;Here for error within an error
ERRERR:	OUTSTR [ASCIZ/Error in writing error file!
/]
	HALT .
;Get and compare NIC version strings ;⊗ VERNIC VERNI1 VERNI2 VERIN VERIN1 VERIN2 VEROUT VEROU1 VEROU2 VERCOM VERCO1

;Get version string from the NIC Host Name Server.  Call:
;	PUSHJ P,VERNIC
;	<error return>
;	<success, version string in NICVER>
VERNIC:	MOVE A,[SRINIC]		;Set host number for NETWRK
	MOVEM A,HOST
	MOVEI A,HNSPRT		;And port number
	MOVEM A,ICPSKT
	PUSHJ P,CONECT		;Call NETWRK subroutine
	 JRST [	PUSHJ P,MTPERR
		MESSAG Can't connect to NIC for version request.]
	 JRST [	PUSHJ P,NIOERR
		MESSAG Can't connect to NIC for version request.]
	MOVEI A,[ASCIZ/VERSION
/]
	PUSHJ P,NETSTR		;Send a version request
	 MESSAG Error in sending version request.
	PUSHJ P,NETSND		;Force output out
	 MESSAG Error in sending version request.
	;Now read in characters until connection closes.
	MOVE C,[POINT 7,NICVER]	;Ptr to start depositing chars
VERNI1:	PUSHJ P,NETICW		;Get a char
	 JRST [	TRNN 0,IODEND	;Connection closed?
		MESSAG I/O error in version request reply.
		JRST VERNI2]
	IDPB 0,C		;Store char
	CAMN C,[POINT 7,NICVER+BUFLEN-1,34] ;Check for overflow
	MESSAG Buffer overflow in version request reply.
	JRST VERNI1		;Back for more

VERNI2:	MOVEI 0,0		;End with a null
	IDPB 0,C
	PUSHJ P,CLOSER		;Call NETWRK to close connection
	JRST CPOPJ1		;And take success return


;Get version string of current NIC host table on disk.  Call:
;	PUSHJ P,VERIN
;	<error return>
;	<success, version string in DSKVER>
VERIN:	SETZM DSKVER		;In case LOOKUP fails
	INIT DVER,0
	 SIXBIT/DSK/
	 DVOBUF,,DVIBUF
	 MESSAG INIT error for version file input.
	SETZM VERFIL+3		;Look on alias area
	LOOKUP DVER,VERFIL
	 JRST CPOPJ1		;If no version file, just return
	MOVE C,[POINT 7,DSKVER]	;Ptr to start depositing chars
VERIN1:	SOSG DVIBUF+2
	IN DVER,
	 JRST VERIN2
	GETSTS DVER,A
	TRNN A,IODEND		;End of file?
	MESSAG Input error on version file.
	TDZA 0,0		;End with a null
VERIN2:	ILDB 0,DVIBUF+1
	IDPB 0,C
	JUMPE 0,CPOPJ1		;Null or EOF marks end
	CAMN C,[POINT 7,DSKVER+BUFLEN-1,34] ;Check for overflow
	MESSAG Buffer overflow in version file input.
	JRST VERIN1		;Back for more


;Output NIC version string to the file.  Call:
;	<call VERIN; leave DVER channel open>
;	 ...
;	PUSHJ P,VEROUT
;	<error return>
;	<success return>
VEROUT:	SETZM VERFIL+3		;Clear PPN clobbered by LOOKUP
	ENTER DVER,VERFIL	;Open in Read-Alter mode
	 MESSAG ENTER error for version file output.
	USETO DVER,0		;Position at beginning
	MOVE C,[POINT 7,NICVER]
VEROU1:	ILDB 0,C
	JUMPE 0,VEROU2		;Check for end
	SOSG DVOBUF+2
	OUT DVER,
	 CAIA
	MESSAG Output error on version file.
	IDPB 0,DVOBUF+1
	JRST VEROU1

VEROU2:	RELEAS DVER,		;Put file in place
	JRST CPOPJ1


;Compare version strings stored in NICVER and DSKVER.  Call:
;	PUSHJ P,VERCOM
;	<return if the same>
;	<return if different>
VERCOM:	MOVE C,[POINT 7,NICVER]	;Set byte pointers
	MOVE D,[POINT 7,DSKVER]
VERCO1:	ILDB A,C		;Get a byte from each string
	ILDB B,D
	JUMPE A,[JUMPN B,CPOPJ1	;Exit if at end of first string
		 POPJ P,]
	JUMPE B,CPOPJ1		;Or second
	CAIN A,(B)		;Compare
	JRST VERCO1		;Keep checking
	JRST CPOPJ1		;Different
;Get new NIC table from Host Name Server ;⊗ NEWNIC NEWNI1 NEWNI2 NEWNI3

IFE FTLLL,<

;Read in a new table from NIC Host Name Server.  Call:
;	PUSHJ P,NEWNIC
;	<error return>
;	<success>
NEWNIC:	MOVEI A,1		;This helps prevent second CONECT losing
	SLEEP A,
	MOVE A,[SRINIC]		;Set host number
	MOVEM A,HOST
	MOVEI A,HNSPRT		;And port number
	MOVEM A,ICPSKT
	PUSHJ P,CONECT
	 JRST [	PUSHJ P,MTPERR
		MESSAG Can't connect to NIC for host table request.]
	 JRST [	PUSHJ P,NIOERR
		MESSAG Can't connect to NIC for host table request.]
	MOVEI A,[ASCIZ/ALL
/]
	PUSHJ P,NETSTR		;Ask for the whole table
	 MESSAG Error in sending host table request.
	PUSHJ P,NETSND		;Force output out
	 MESSAG Error in sending host table request.

	INIT DOUT,0		;Get ready to write new file
	 SIXBIT/DSK/
	 DOBUF,,0
	 MESSAG INIT error for host table output.
	MOVEI A,DOUT
	SHOWIT A,
	SETZM HSTFIL+3		;Write file on our area
	ENTER DOUT,HSTFIL
	 MESSAG ENTER error for host table output.
	MOVEI A,346		;Lowcore pointer for optimal number of buffers
	PEEK A,
	HLRZ A,A
	OUTBUF DOUT,(A)
	MOVEI C,0		;Initialize byte count
	MOVEI E,ENDMK		;Initialize endmark tester

NEWNI1:	PUSHJ P,NETICW		;Get a character from the network
	 JRST [ TRNN 0,IODEND	;Test for connection close
		MESSAG I/O error in host table request reply.
		JRST NEWNI3]
	SOSG DOBUF+2		;Output the character
	OUT DOUT,
	 CAIA
	MESSAG Output error in writing host table file.
	IDPB 0,DOBUF+1
	SKIPGE E		;Skip unless already seen endmark
	AOJA C,NEWNI1		;Go back for more
	CAMN 0,(E)		;Compare current char to next in endmark
	AOJA E,NEWNI2		;If same, set up for next char
	MOVEI E,ENDMK		;If different, start test at beginning
	AOJA C,NEWNI1		;Go back for more

NEWNI2:	CAIN E,ENDEND		;Matched entire endmark?
	SETOM E			;Yes, note this
	AOJA C,NEWNI1		;And go finish input

NEWNI3:	OUT DOUT,		;Do last output
	 CAIA
	MESSAG Output error in writing host table file.
;	SKIPL E			;Was endmark seen?
;	MESSAG Endmark of NIC host table not received.
;JJW 12-Oct-86 -- Took out above lines since it happens to often.
;We'll have to manually patch the table each time, until Argus is fixed.
	SKIPL E			;Was endmark seen?
	OUTSTR [ASCIZ/*** Endmark of NIC host table not received. ***
/]				;No, make sure we notice it
	RELEAS DOUT,		;Yes, put new file in place
	PUSHJ P,CLOSER		;Close net connection
	JRST CPOPJ1		;And take success return

>;IFE FTLLL
;FTP new HOSTS3.BIN from NIC ;⊗ NEWNIC NEWNI1 NEWNI2 NEWNI3

IFN FTLLL,<

;Call:
;	PUSHJ P,NEWNIC
;	<error return>
;	<success>
NEWNIC:	PTYGET A		;Get a PTY, returns line number in A
	 MESSAG PTYGET for FTP failed.
	MOVEI B,5		;PTJOBX LOGIN code
	PTJOBX A		;Login a job
	 MESSAG Couldn't login job on PTY for FTP.
	MOVEM B,PTYJOB		;Save job number
	MOVEI B,FTPCOM		;Get FTP command line
	PTWRS7 A		;Type it on the PTY
	;Now loop, waiting for FTP to finish, or some error.
	MOVEI D,=300		;Time out after 300 tries (10 mins)
	MOVEI C,2		;Number of seconds per try
NEWNI1:	SLEEP C,		;Sleep 2 seconds
NEWNI2:	PTRD1S A		;Empty PTY's output buffer
	 JRST NEWNI3		;Nothing more to read
	OUTCHR B		;Show what it said
	JRST NEWNI2		;Go back for more

NEWNI3:	MOVE B,PTYJOB		;Check FTP job's runtime
	RUNTIM B,
	CAIL B,=120000		;Don't let it use more than 120 cpu secs
	JRST [	PTYREL A	;It's probably looping; kill it
		MESSAG FTP aborted after 120 cpu seconds.]
	MOVEI B,6		;PTJOBX IWAITS code
	PTJOBX A		;Is it waiting for input?
	 JRST [ SOJG D,NEWNI1	;No, keep waiting (unless timeout)
		PTYREL A	;Looks like it's hung
		MESSAG FTP aborted after 10 elapsed minutes.]
	PTYREL A		;I think we succeeded!
	;At this point, we should probably do some consistency checks on the
	;binary file, having FTPed it to a different name temporarily, and
	;then rename it to HOSTS3.BIN if all OK.
	JRST CPOPJ1		;Success return

>;IFN FTLLL
;Read PUP directory version number ;⊗ RDPVER RDPDIR

IFN FTPUP,<			;Several pages

;Here to read saved version number from PUP network directory on disk.  Call:
;	PUSHJ P,RDPVER
;	<error return>
;	<success, version number in PUPDSV>
RDPVER:	INIT DIN,17		;Open disk input in dump mode
	 SIXBIT/DSK/
	 0
	 MESSAG INIT error for PUP network directory input.
	SETZM DIRFIL+3		;Read file on our area
	LOOKUP DIN,DIRFIL
	 JRST CPOPJ1		;Just return if no file
	IN DIN,[IOWD DIRHLN,DIRHDR ↔ 0]	;Read the header
	 CAIA
	MESSAG Input error for PUP network directory.
	LDB A,VERPTR		;Get version number
	MOVEM A,PUPDSV		;Store as disk version number
	JRST CPOPJ1

;Here to read the entire PUP network directory into core (only used when
;hacking PUPHST on the directory we already have).
;	PUSHJ P,RDPDIR
;	<error return>
;	<success, location of directory in PUPDIR>
RDPDIR:	INIT DIN,17		;Open disk input in dump mode
	 SIXBIT/DSK/
	 0
	 MESSAG INIT error for PUP network directory input.
	SETZM DIRFIL+3		;Read file on our area
	LOOKUP DIN,DIRFIL
	 JRST CPOPJ1		;Just return if no file
	HRRZ A,JOBFF↑		;Place to read in the data
	MOVEM A,PUPDIR
	MOVEI B,-1(A)		;Make IOWD in B
	HLL B,DIRFIL+3
	MOVS C,DIRFIL		;Negative of file size
	SUBI A,1(C)		;Highest location we need
	CORE A,			;Get core for input file
	 MESSAG CORE UUO failed.
	SETZ C,			;End dump mode command list
	IN DIN,B		;Input the PUP directory
	 CAIA
	MESSAG Input of PUP directory failed.
	MOVE A,VERPTR		;Get ptr to version number
	SUBI A,DIRHDR		;Relocate to our location
	ADD A,PUPDIR
	LDB A,A			;Get version number
	MOVEM A,PUPDSV		;Store as disk version number
	JRST CPOPJ1
;Get PUP version from Ethernet ;⊗ GETVER GETVE1

;This page IFN FTPUP

;Here to get version number from misc servers on the Ethernet.  Assumes
;our version number is already in PUPDSV.  Call:
;	PUSHJ P,GETVER
;	<error return>
;	<success, highest version number in PUPMSV, host in PUPMHS>
GETVER:	MOVE A,PUPDSV		;Our version
	MOVEM A,PUPMSV		;Is best so far
	INIT PUPVER,15		;Packet mode
	 SIXBIT/PUP/
	 0			;No buffers
	 MESSAG INIT error for PUP version request.
	MTAPE PUPVER,VERLSN	;Listen
	SKIPE VERSTS
	 MESSAG Error in LISTEN MTAPE for PUP version request.
	SETZM PKTBUF		;Clear out old header, so WAITS fills this
	MOVE A,[PKTBUF,,PKTBUF+1] ;stuff in.
	BLT A,PKTBFD
	MOVEI A,240		;Set packet type to NetDirVersion
	DPB A,PKTTYP
	MOVE A,PUPDSV		;Get our version number
	DPB A,[POINT 16,PKTBFD,15] ;Store in packet
	MOVEI A,PUPOVH+2	;Length = overhead + 2 data bytes
	DPB A,PKTLEN
	ADDI A,2+2+3		;Plus Ethernet header plus rounding
	LSH A,-2		;Convert to words
	HRLOI A,-1(A)		;<len-1>,,-1
	EQVI A,PKTBUF-1		;<-len>,,PKTBUF-1
	SETZ B,			;End IOWD list
	OUT PUPVER,A		;Send the packet
	 CAIA
	MESSAG Error in PUP version request output.
	MOVEI C,5		;Number of seconds to wait for replies
	MOVEI D,1
GETVE1:	MTAPE PUPVER,[10]	;Skip if input available
	 JRST [	SOJL C,CPOPJ1	;We can't wait forever
		SLEEP D,	;Wait one second
		JRST GETVE1]	;Try again
	IN PUPVER,[IOWD PUPMAX,PKTBUF ↔ 0] ;Read packet
	 CAIA
	MESSAG Input error in PUP version reply.
	LDB A,PKTTYP		;Check reply type
	LDB B,[POINT 16,PKTBFD,15] ;And version number
	CAIN A,240		;NetDirVersion?
	CAMGE B,PUPMSV		;At least as good as best so far?
	JRST GETVE1		;No, ignore it
	LDB A,PKTSRC		;Get source of this reply
;JJW - some hosts on both nets 44# and 10# send us a reply with their
;net 10# address, but we hang if we try to open a connection to them.
;	LSH A,-8		;Get subnet number
;	CAIE A,44		;Is it net 44#?
;	JRST GETVE1		;No, ignore
;	LDB A,PKTSRC		;Get source address again
;(above code removed 12 Oct 86 -- see next page)
	MOVEM A,PUPMHS		;Save host number
	MOVEM B,PUPMSV		;This is the best version now
	LDB A,PKTDST		;Get our own address while we're at it
	MOVEM A,OURHST		;We'll need it later
	JRST GETVE1		;Keep trying until tired
;Get new PUP directory ;⊗ GNPDIR GNPDI1 GNPDI2 GNPDI3 GNPDI4 GETCOR GETCO1

;This page IFN FTPUP

;Here to get new PUP network directory from host in PUPMHS.  Call:
;	PUSHJ P,GNPDIR
;	<error return>
;	<success return>
GNPDIR:	INIT PUPEFT,13		;EFTP mode
	 SIXBIT/PUP/
	 0,,PUPIBF
	 MESSAG INIT failure for EFTP channel.
	MOVEI A,=8		;Change byte size
	DPB A,[POINT 6,PUPIBF+1,11] ;in buffer header
	INBUF PUPEFT,2		;Set up buffer ring
	MOVE A,PUPMHS		;Set host number in MTAPE blocks
	MOVEM A,VERHST
;	MOVEM A,EFTHST
;JJW 12-Oct-86 -- Took out above line since multihomed Vaxes may use a
;different address.
	SETOM EFTHST		;Accept connection from any address
	MTAPE PUPEFT,EFTGEN	;Gensym a socket for EFTP
	MOVE A,EFTGSK		;Copy into listen block
	MOVEM A,EFTLSK
	MTAPE PUPEFT,EFTLSN	;Listen on EFTP channel
	SKIPE EFTSTS		;Check status bits
	MESSAG Error in LISTEN MTAPE for PUP directory update.
	MTAPE PUPVER,VERTRM	;Close previous connection on PUPVER
	MTAPE PUPVER,VERCON	;Get new connection to this host
	SKIPE VCNSTS
	MESSAG Error in CONNECT MTAPE for PUP directory update.
	SETZM PKTBUF		;Clear out old header, so WAITS fills this
	MOVE A,[PKTBUF,,PKTBUF+1] ;stuff in.
	BLT A,PKTBFD
	MOVEI A,241		;Packet type SendNetDir
	DPB A,PKTTYP
	MOVE A,OURHST			;Our host number
	DPB A,[POINT 16,PKTBFD,15]	;is first part of port number
	MOVE A,EFTGSK			;EFTP socket
	DPB A,[POINT 16,PKTBFD+1,15]	;is the rest
	LSH A,-=16
	DPB A,[POINT 16,PKTBFD,31]
	MOVEI A,PUPOVH+6	;Length = overhead + 6 data bytes
	DPB A,PKTLEN
	ADDI A,2+2+3		;Plus Ethernet header plus rounding
	LSH A,-2		;Convert to words
	HRLOI A,-1(A)		;<len-1>,,-1
	EQVI A,PKTBUF-1		;<-len>,,PKTBUF-1
	SETZ B,			;End IOWD list
	OUT PUPVER,A		;Send the packet
	 CAIA
	MESSAG Error in PUP directory request output.
	RELEAS PUPVER,		;Done with version request channel
	;Now EFTP the directory into core.
	MOVE A,JOBFF↑
	PUSHJ P,GETCOR		;Clear core, set C to bytes cleared
	HRRZ B,JOBFF↑		;Start storing here
	HRLI B,(<POINT 8,0>)	;Make byte ptr to IDPB
GNPDI1:	SOSG PUPIBF+2		;See if there's more EFTP input
	IN PUPEFT,
	 CAIA			;Yes, there is
	JRST GNPDI4		;No, check for end
GNPDI2:	SOJGE C,GNPDI3		;Jump if there's room for this byte
	MOVEI A,1(B)		;No room.  Get address of next word to store
	PUSHJ P,GETCOR		;Get and clear some core
	SOS C			;Fix byte count
GNPDI3:	ILDB A,PUPIBF+1		;Load byte
	IDPB A,B		;Store byte
	JRST GNPDI1		;Continue copying

GNPDI4:	STATO PUPEFT,IODEND	;End of input?
	 MESSAG Error in PUP directory input.
	RELEAS PUPEFT,		;Yes, all done with EFTP channel
	INIT DOUT,17		;Open disk output channel in dump mode
	 SIXBIT/DSK/
	 0
	 MESSAG Disk INIT failure in writing PUP directory.
	SETZM DIRFIL+3		;Write file on our area
	ENTER DOUT,DIRFIL	;Enter directory file
	 MESSAG ENTER error in writing PUP directory.
	HRRZ A,JOBFF↑		;Addr of start of data
	MOVEM A,PUPDIR		;Store for PUPHST
	SUBI A,1		;-1 for IOWD
	SUBM A,B		;-<word count> in RH(B)
	HRL A,B			;Make IOWD
	SETZ B,			;End IOWD list
	OUT DOUT,A		;Do dump mode output
	 CAIA
	MESSAG Output error in writing PUP directory file.
	RELEAS DOUT,
	JRST CPOPJ1		;All done, hooray!

;Here to clear core and expand if necessary.
;Call:	MOVE A,<starting address of core to clear>
;	PUSHJ P,GETCOR
;	<return with core cleared from (A) to JOBREL, byte count in C>
GETCOR:	CAMGE A,JOBREL↑		;Need more core?
	JRST GETCO1		;No.  (Must be first call to GETCOR)
	MOVEI C,1777(A)		;Yes, get 2 pages
	CORE C,
	 MESSAG CORE UUO failed in PUP directory input.
GETCO1:	SETZM (A)		;Zero first word
	MOVEI C,1(A)		;Make BLT word
	HRLI C,(A)
	BLT C,@JOBREL↑		;Clear core
	MOVE C,JOBREL↑
	SUBI C,-1(A)		;Count of words gotten
	LSH C,2			;Times 4 for 8-bit bytes
	POPJ P,
;File output routines ;⊗ PUTCH PUTCH1 PUTSTR PUTST1 PUTDEC PUTOCT PUTOC1 PUTSIX PUTDAT MONTH

;Output a character in A.
PUTCH:	SOSG DOBUF+2
	OUT DOUT,
	 JRST PUTCH1
;Here we have an output error.  Unwind stack to level of call to PUPHST and
;return error message.
	MOVE P,PUPHSP
	MESSAG Output error in writing PUPHST file.

PUTCH1:	IDPB A,DOBUF+1
	POPJ P,

;Output an ASCIZ string with address or byte ptr in B.  Clobbers A and B.
PUTSTR:	TLNN B,-1		;Byte ptr?
	HRLI B,440700		;No, make one
PUTST1:	ILDB A,B		;Get a char
	JUMPE A,CPOPJ		;Return if done
	PUSHJ P,PUTCH		;Output it
	JRST PUTST1

;Output an octal or decimal number in A.  Clobbers A, B, and C.
PUTDEC:	SKIPA C,[=10]
PUTOCT:	MOVEI C,10
PUTOC1:	IDIV A,C
	HRLM B,(P)
	JUMPE A,.+2
	PUSHJ P,PUTOC1
	HLRZ A,(P)
	ADDI A,"0"
	JRST PUTCH

;Output a left-adjusted sixbit word in B.  Clobbers A and B.
PUTSIX:	JUMPE B,CPOPJ
	SETZ A,
	LSHC A,6
	ADDI A,40
	PUSHJ P,PUTCH
	JRST PUTSIX

;Output the date in system date format in A.  Clobbers A and B.
PUTDAT:	IDIVI A,=31		;Get day of month - 1 in B
	PUSH P,A		;Save the rest
	MOVEI A,1(B)
	PUSHJ P,PUTDEC
	POP P,A
	IDIVI A,=12		;Get month - 1 in B
	PUSH P,A		;Save the rest
	MOVE B,MONTH(B)		;Get ASCII month
	PUSHJ P,PUTSTR
	POP P,A			;Get year - 1964
	ADDI A,=64
	JRST PUTDEC

MONTH:	[ASCIZ/-Jan-/]
	[ASCIZ/-Feb-/]
	[ASCIZ/-Mar-/]
	[ASCIZ/-Apr-/]
	[ASCIZ/-May-/]
	[ASCIZ/-Jun-/]
	[ASCIZ/-Jul-/]
	[ASCIZ/-Aug-/]
	[ASCIZ/-Sep-/]
	[ASCIZ/-Oct-/]
	[ASCIZ/-Nov-/]
	[ASCIZ/-Dec-/]
;More subroutines ;⊗ IPTEST IPTES1 IPTES2 IPTES3 OUTADR OUTAD1 OUTNAM OUTNLP COMPAR COMPLP COMPL1 COMPL2 CMPLUZ PUTATR PUTALP PUTAT1

;Search for "IP" in "Networks" attribute, and set SHOWIP non-0 if found.
IPTEST:	SETZM SHOWIP		;Default not to show IP address
	SKIPN C,NETPTR		;Is there a Networks attribute?
	POPJ P,			;No
	LSH C,-1		;Get PDP-10 address of string
	ADD C,PUPDIR
	HRLI C,(<POINT 8,0>)	;Make byte ptr
	ILDB B,C		;Get byte count
	MOVEI A,0		;"previous" character
IPTES1:	SOJL B,CPOPJ		;Jump at end of string
	MOVEI X,(A)		;Save previous character
	ILDB A,C		;Get a byte
	CAIE A,"I"		;Looking for "I"
	JRST IPTES1		;Haven't found it yet
	TRZ X,40		;Map lower to upper
	CAIL X,"A"		;Was previous char a letter?
	CAILE X,"Z"
	CAIA			;No, good.
	JRST IPTES1		;Keep hunting for delimited "I"
IPTES2:	SOJL B,CPOPJ
	ILDB A,C		;Get next char
	CAIE A,"P"		;Give me a "P"
	JRST IPTES1		;No such luck, start over
	SOJL B,IPTES3		;If done now, we got "IP"
	ILDB A,C		;Else check another
	TRZ A,40
	CAIL A,"A"
	CAILE A,"Z"
	CAIA			;"IP" followed by non-letter wins
	JRST IPTES1		;"IP" followed by letter loses
IPTES3:	SETOM SHOWIP		;Set flag to show IP addresses in OUTADR
repeat 0,<		;No longer needed
	SKIPN C,PRTPTR		;One more kludgy test before we're done
	POPJ P,
	LSH C,-1		;Get addr of protocol list
	ADD C,PUPDIR
	MOVE B,(C)
	CAMN B,[BYTE (8)3,"B","A","D"]	;This is set for SU-DSN to say
	SETZM SHOWIP		;they're really not running Ethernet IP
>;repeat 0
	POPJ P,

;Here to output all addresses for address pointer in A.
OUTADR:	LSH A,-1		;Get PDP-10 address of address block
	ADD A,PUPDIR
	MOVEI X,(A)
	HRLI X,442000		;Byte ptr to beginning of address block
	ILDB A,X		;Get pointer to next address
	PUSH P,A		;Save it
	IBP X			;Skip pointer to owning entry block
	MOVEI B,[ASCIZ/SU /]
	PUSHJ P,PUTSTR
	ILDB A,X		;Get address
	PUSH P,A		;Save it
repeat 0,<
	MOVSI B,-DOMNUM		;Set up to check for domain names
	CAME A,DOMHST(B)
	AOBJN B,.-1
	JUMPGE B,.+3		;Jump if AOBJN exhausted
	MOVE B,DOMNAM(B)
	MOVEM B,DOMSTR
>;repeat 0
	LSH A,-10		;Get subnet number
	PUSHJ P,PUTOCT
	MOVEI A,"#"
	PUSHJ P,PUTCH
	MOVE A,(P)		;Get back address
	ANDI A,377		;Get host number
	PUSHJ P,PUTOCT
	SKIPN SHOWIP		;Skip if showing IP address
	JRST OUTAD1
	MOVEI B,[ASCIZ/, 36./]
	PUSHJ P,PUTSTR
	MOVE A,(P)
	LSH A,-10		;Subnet
	PUSHJ P,PUTDEC
	MOVEI B,[ASCIZ/.0./]
	PUSHJ P,PUTSTR
	MOVE A,(P)
	ANDI A,377		;Host
	PUSHJ P,PUTDEC
OUTAD1:	POP P,A			;Pop saved address
	POP P,C			;Get back next address block pointer
	JUMPE C,CPOPJ		;Zero marks end
	MOVEI B,[ASCIZ/, /]
	PUSHJ P,PUTSTR
	MOVE A,C
	JRST OUTADR		;Print next address

;Here to output all names for name pointer in A.
OUTNAM:	SETOM ONMFST#		;Set flag for first time through
OUTNM1:	PUSH P,A		;Save pointer to current name
	LSH A,-1		;Get PDP-10 address of name block
	ADD A,PUPDIR
	MOVEI X,(A)
	HRLI X,442000		;Byte ptr to beginning of name block
	ILDB A,X		;Get pointer to next name
	PUSH P,A		;Save it
	IBP X			;Skip pointer to owning entry block
	TLC X,3000		;Convert to 8-bit byte ptr
	ILDB B,X		;Get number of bytes in string
OUTNLP:	ILDB A,X		;Get a character
;;	CAIL A,"a"
;;	CAILE A,"z"
;;	CAIA
;;	SUBI A,"a"-"A"		;Force uppercase
	PUSHJ P,PUTCH		;Output the character
	SOJG B,OUTNLP		;Repeat till done
	MOVEI B,[ASCIZ/.Stanford.EDU/]	;Domain string
	SKIPN ONMFST		;If repeating primary name,
	PUSHJ P,PUTSTR		;Append domain
	POP P,C			;Get back next name block pointer
	POP P,A			;And pointer for current name
;This code not installed yet
;;	AOSN ONMFST		;If first time through,
;;	MOVE C,A		;Repeat current name with domain
	JUMPE C,CPOPJ		;Zero marks end
	MOVEI B,[ASCIZ/, /]
	PUSHJ P,PUTSTR
	MOVE A,C
	JRST OUTNM1		;Print next name

;Here to compare an attribute name with a fixed string.
;Call:	MOVE A,<directory address of name>
;	PUSHJ P,COMPAR
;	 ASCIZ/string/
;	 <return here if equal>
;	<return here if not equal>
;Preserves A, B, and C.
COMPAR:	PUSH P,A		;Preserve ACs
	PUSH P,B
	PUSH P,C
	MOVSI C,(<POINT 7,0>)	;Make byte pointer
	HLLM C,-3(P)
	LSH A,-1		;Get PDP-10 address of name string
	ADD A,PUPDIR
	HRLI A,(<POINT 8,0>)	;Make byte pointer
	ILDB B,A		;Get character count
COMPLP:	ILDB C,-3(P)		;Get byte from fixed string
	JUMPE C,COMPL2		;Jump if end of fixed string
	SOJL B,COMPL1		;Jump if end of name string
	ILDB D,A		;Get byte from name string
	CAIN C,(D)		;See if the same
	JRST COMPLP		;Yes, go back for more if any
	;Here when match fails or name string runs out before fixed string
COMPL1:	ILDB C,-3(P)		;Zap to end of fixed string
	JUMPN C,COMPL1
	JRST CMPLUZ		;Failed
	;Here when at end of fixed string
COMPL2:	SKIPE B			;Both strings ended
CMPLUZ:	AOS -3(P)
	POP P,C			;Restore ACs
	POP P,B
	POP P,A
	JRST CPOPJ1		;Jump over string

;Here to output a string, all uppercased, followed by a colon.
;Call:	MOVE C,<address in directory>
;	PUSHJ P,PUTATR
PUTATR:	MOVEI A,":"		;Print this
	JUMPE C,PUTCH		;If no entry
	MOVEI A," "		;Else start with a space
	PUSHJ P,PUTCH
	LSH C,-1
	ADD C,PUPDIR
	HRLI C,(<POINT 8,0>)	;Make byte ptr
	ILDB B,C		;Get byte count
PUTALP:	SOJL B,PUTAT1		;Return when all done
	ILDB A,C		;Get a byte
;;	CAIL A,"a"		;Force uppercase
;;	CAILE A,"z"
;;	CAIA
;;	SUBI A,"a"-"A"
	PUSHJ P,PUTCH		;Output the character
	JRST PUTALP		;Back for more
PUTAT1:	MOVEI B,[ASCIZ/ :/]	;End text
	JRST PUTSTR
;Create PUPHST.TXT file ;⊗ PUPHST HDRLP MAINLP ALLDUN REDENT ATTLP ATTLP1 SHORT PRCENT

PUPHST:	INIT DOUT,0		;Open output file in buffer mode
	 SIXBIT/DSK/
	 DOBUF,,0
	 MESSAG INIT failure for PUPHST output channel
	ENTER DOUT,PHSFIL
	 MESSAG ENTER failure for PUPHST output file
	MOVEM P,PUPHSP		;Save PDL ptr in case of output error
	MOVSI A,-HDRSIZ		;Set up to copy header block
	MOVE B,PUPDIR
	HRLI B,442000		;Byte ptr to beginning of directory
HDRLP:	ILDB C,B		;Get a 16-bit word
	MOVEM C,NUMNAM(A)	;Store it
	AOBJN A,HDRLP
	MOVE A,FSTENT		;First entry block
	LSH A,-1		;Make PDP-10 address
	ADD A,PUPDIR
	HRLI A,442000		;Make byte ptr
	MOVEM A,ENTPTR		;And save it
	;Include date, time and PPN of file writer.
	MOVEI B,[ASCIZ/;Stanford PUP network directory.  Created by [/]
	PUSHJ P,PUTSTR
	GETPPN C,
	HLLZ B,C
	PUSHJ P,PUTSIX
	MOVEI A,","
	PUSHJ P,PUTCH
	HRLZ B,C
	PUSHJ P,PUTSIX
	MOVEI B,[ASCIZ/] using UPDATE on /]
	PUSHJ P,PUTSTR
	DATE A,
	PUSHJ P,PUTDAT
	MOVEI B,[ASCIZ/.
;Source was Pup network directory version /]
	PUSHJ P,PUTSTR
	MOVE A,PUPMSV
	PUSHJ P,PUTDEC
	MOVEI B,[ASCIZ/.

NET : SU 0#0 : SU-ETHERNET :

/]
	PUSHJ P,PUTSTR
;
;Now go through all of the entries.
;
MAINLP:	PUSHJ P,REDENT		;Read entry
	 POPJ P,		;Error in an entry
	 JRST ALLDUN		;No more
	PUSHJ P,PRCENT		;Process entry
	JRST MAINLP		;Continue

ALLDUN:	RELEAS DOUT,
	JRST CPOPJ1		;Success return


;Read an entry from the PUP network directory, saving pointers.  Return
;	+1 on error
;	+2 if done directory
;	+3 if an entry was read
REDENT:	SOSGE NUMENT		;Count down entry words
	 JRST CPOPJ1		;Got 'em all
	ILDB A,ENTPTR		;Pointer to 1st name block
	JUMPE A,CPOPJ1		;It might end this way
	MOVEM A,NAMPTR		;Save it
	SOSGE NUMENT		;Count down entry words
	 JRST SHORT		;Ended early.  Print message and fail
	ILDB A,ENTPTR		;Pointer to 1st address block
	MOVEM A,ADRPTR		;Save it
	SOSGE NUMENT		;Count down entry words
	 JRST SHORT
	ILDB C,ENTPTR		;Get number of attributes
	SETZM CPUPTR		;Zero attribute pointers
	SETZM OPSPTR
	SETZM NETPTR
	SETZM PRTPTR
ATTLP:	SOJL C,ATTLP1		;Count down attributes
	SOSGE NUMENT		;Count down entry words
	 JRST SHORT
	ILDB A,ENTPTR		;Get attribute name
	SOSGE NUMENT		;Count down entry words
	 JRST SHORT
	ILDB B,ENTPTR		;Get attribute value
	PUSHJ P,COMPAR		;See if it's one of the attributes we want
	 ASCIZ/CPU/
	 MOVEM B,CPUPTR
	PUSHJ P,COMPAR
	 ASCIZ/Op-Sys/
	 MOVEM B,OPSPTR
	PUSHJ P,COMPAR
	 ASCIZ/Networks/
	 MOVEM B,NETPTR
	PUSHJ P,COMPAR
	 ASCIZ/IP-Protocols/
	 MOVEM B,PRTPTR
	JRST ATTLP		;Back for more
ATTLP1:	IBP ENTPTR		;Bump the pointer, since an entry block is always
				;of odd size, but next block starts on a word
	JRST CPOPJ2		;Double skip return on success

SHORT:	MESSAG Inconsistency in input file - ended in middle of entry block

;Process the entry just read.  Always returns non-skip.
PRCENT:	;Peek ahead at first address block.  If subnet number or host number is
	;zero, then this isn't a host entry and we don't want to output any-
	;thing.  Also, if the socket number is non-zero, we want to ignore it.
	MOVE A,ADRPTR
	LSH A,-1		;Get PDP-10 word address
	ADD A,PUPDIR
	LDB H,[POINT 16,1(A),15];Subnet and host number
	LDB B,[POINT 16,1(A),31];First 16 bits of socket
	LDB C,[POINT 16,2(A),15];Last 16 bits of socket
	TRNE H,177400		;If subnet is zero
	TRNN H,377		;Or host is zero
	POPJ P,			;Then do nothing
	JUMPN B,CPOPJ		;If either part of socket number is non-zero
	JUMPN C,CPOPJ		;Then do nothing
	CAIN H,177777		;Ignore host 377#377 ("NetDirBuilt")
	POPJ P,
	MOVEI B,[ASCIZ/HOST : /]
	PUSHJ P,PUTSTR
	PUSHJ P,IPTEST		;See whether this is an IP host
repeat 0,<
	SETZM DOMSTR		;Clear ptr to domain-style name
>;repeat 0
	MOVE A,ADRPTR
	PUSHJ P,OUTADR		;Output all addresses, set DOMNAM if needed
	MOVEI B,[ASCIZ/ : /]
	PUSHJ P,PUTSTR
repeat 0,<
	SKIPE B,DOMSTR		;Skip unless there's a domain-style name
	PUSHJ P,PUTSTR		;Output domain name
>;repeat 0
	MOVE A,NAMPTR		;Get back name pointer
	PUSHJ P,OUTNAM		;Output all names
	MOVEI B,[ASCIZ/ :/]
	PUSHJ P,PUTSTR
	MOVE C,CPUPTR		;Now put out the attributes in the right order
	PUSHJ P,PUTATR
	MOVE C,OPSPTR
	PUSHJ P,PUTATR
	MOVE C,PRTPTR
	PUSHJ P,PUTATR
	MOVEI B,[ASCIZ/
/]
	JRST PUTSTR		;End of an entry

>;IFN FTPUP
;Top level ;⊗ NICUPD NICERR PUPUPD PUPERR PUPHAK UPDATE PPNOK NOERRS

NICUPD:	OUTSTR [ASCIZ/Getting latest version number from NIC name server.
/]
	PUSHJ P,VERNIC		;Get NIC directory version string
	 JRST NICERR		;Error of some kind
	OUTSTR [ASCIZ/NIC's version string is /]
	OUTSTR NICVER
	OUTSTR CRLF
	PUSHJ P,VERIN		;Get version from disk file
	 JRST NICERR		;Error
	OUTSTR [ASCIZ/Saved version string is /]
	OUTSTR DSKVER
	OUTSTR CRLF
	PUSHJ P,VERCOM		;Compare version strings
	 JRST [	OUTSTR [ASCIZ/No update of NIC host table needed.
/]
		POPJ P,]
	OUTSTR [ASCIZ/Getting new host table from NIC name server.
/]
	PUSHJ P,NEWNIC		;Read in the new host table
	 JRST NICERR		;Some error
	PUSHJ P,VEROUT		;Output version string to file
	 JRST NICERR		;Some error
	OUTSTR [ASCIZ/New host table successfully installed.
/]
	SETOM CHANGE		;Indicate change
	POPJ P,

NICERR:	RELEAS DVER,3		;Don't write any files!
	RELEAS DOUT,3
	POPJ P,

IFN FTPUP,<
PUPUPD:	PUSHJ P,RDPVER		;Read version from PUP directory on disk
	 JRST PUPERR		;Error
	OUTSTR [ASCIZ/Our PUP network directory is version /]
	MOVE A,PUPDSV
	PUSHJ P,DECOUT
	OUTSTR CRLF
	PUSHJ P,GETVER		;Get version from misc servers
	 JRST PUPERR		;Error of some kind
	MOVE A,PUPMSV		;Highest version reported
	CAMG A,PUPDSV		;Compare with our version
	 JRST [	OUTSTR [ASCIZ/No update of PUP network directory needed.
/]
		POPJ P,]
	OUTSTR [ASCIZ/Getting new PUP directory version /]
	PUSHJ P,DECOUT		;Output version in A
	OUTSTR [ASCIZ/ from host /]
	LDB A,[POINT 8,PUPMHS,27]
	PUSHJ P,OCTOUT		;Subnet
	OUTCHR ["#"]
	LDB A,[POINT 8,PUPMHS,35]
	PUSHJ P,OCTOUT		;Host
	OUTSTR CRLF
	PUSHJ P,GNPDIR		;Get new PUP directory
	 JRST PUPERR		;Some error
	OUTSTR [ASCIZ/New PUP directory successfully installed.
/]
	PUSHJ P,PUPHST		;Write new PUPHST.TXT file
	 JRST PUPERR
	OUTSTR [ASCIZ/PUPHST output file compiled successfully.
/]
	SETOM CHANGE		;Indicate change
	POPJ P,

PUPERR:	RELEAS DOUT,3		;Don't write file
	POPJ P,
>;IFN FTPUP

PUPHAK:
IFN FTPUP,<
	PUSHJ P,RDPDIR		;Get the current PUP network directory
	 EXIT			;Some error
	OUTSTR [ASCIZ/PUP directory version /]
	MOVE A,PUPDSV
	MOVEM A,PUPMSV		;Set version number for output file
	PUSHJ P,DECOUT
	OUTSTR CRLF
	PUSHJ P,PUPHST		;Make a new PUPHST.TXT
	 PUSHJ P,PUPERR		;Unless there's an error
	OUTSTR [ASCIZ/PUPHST output file compiled successfully.
/]
>;IFN FTPUP
	EXIT

	TDZA D,D		;Start -1 to run PUPHST on existing directory
UPDATE:	MOVEI D,1		;Normal start
	RESET
	MOVE P,[IOWD PDLEN,PDL]
	MOVEI A,0		;Code to lookup disk PPN
	DSKPPN A,		;What's our alias?
	CAMN A,['HSTNET']	;Is it the expected?
	JRST PPNOK		;Yes
	OUTSTR [ASCIZ/You are not aliased to [HST,NET].  Do you want to proceed,
with files read and written from your alias area (Y or N)? /]
	INCHRW A		;Get a char
	CAIE A,15
	OUTSTR CRLF
	CAIN A,15		;Ho hum
	INCHRW A
	CAIE A,"Y"
	CAIN A,"y"
	JRST PPNOK
	EXIT

PPNOK:	JUMPE D,PUPHAK		;Jump if special start
	PUSHJ P,NICUPD		;Update NIC table
IFN FTPUP,<
	OUTSTR [ASCIZ/--------------------------------------------------
/]
	PUSHJ P,PUPUPD		;Update PUP table
>;IFN FTPUP
	SKIPN ERRORS		;Were there errors?
	JRST NOERRS
	MOVEI A,[ASCIZ/UPDATE aborted due to errors.
/]
	PUSHJ P,MESTYP
	PUSHJ P,MAILMS		;Mail errors to interested people
	EXIT

NOERRS:	SKIPN CHANGE		;Did anything change?
	EXIT			;No, all done
	OUTSTR CRLF
IFE FTLLL,<
	MOVEI A,[ASCIZ/New NIC or PUP table installed.  Please check the log and run HOSTS3.
/]
>;IFE FTLLL
IFN FTLLL,<
	MOVEI A,[ASCIZ/New HOSTS3.BIN from NIC installed on [HST,NET] at S1-A.
/]
>;IFN FTLLL
	PUSHJ P,MESTYP
	PUSHJ P,MAILMS
	EXIT

	END UPDATE